import {
  NavigationGuardNext,
  _RouteLocationBase,
  RouteRecordRaw
} from "vue-router";

import ProjectConfig from "@/settings/projectSetting";

import NotAllowedError from "@/error/NotAllowedError";
//验证token是否存在
import { getToken } from "@/utils/auth";
import { buildMenus } from "@/api/system/menu";

import store from "@/store";

import { asyncRouter } from "@/store/modules/permission";

// 进度条工具样式
import NProgress from "nprogress";
import "nprogress/nprogress.css";
import type { Router } from "vue-router";
import { setRouteChange } from "@/logics/mitt/routeChange";

function createHttpGuard(router: Router) {
  NProgress.configure({
    showSpinner: false,
  });
  //进度条配置
  // 全局解析守卫
  router.beforeResolve(async (to) => {
    // 如果用户自定义meta属性存在
    // 获取数据或执行任何其他操作（如果用户无法进入页面时你希望避免执行的操作）的理想位置
    if (to.meta.requiresCamera) {
      try {
        // await askForCameraPermission()
      } catch (error) {
        if (error instanceof NotAllowedError) {
          // ... 处理意料之内的错误，然后取消导航
          return false;
        } else {
          // 意料之外的错误，取消导航并把错误传给全局处理器
          throw error;
        }
      }
    }
  });

  //   全局前置守卫，当一个导航触发时，全局前置守卫按照创建顺序调用
  router.beforeEach(
    (
      to: _RouteLocationBase,
      from: _RouteLocationBase,
      next: NavigationGuardNext
    ) => {
      NProgress.start(); //开始进度条
      if (to.meta.title) {
        document.title = to.meta.title + " - " + ProjectConfig.title;
      }

      // 本地缓存存在token已经验证通过
      const isAuthenticated = getToken();
      if (isAuthenticated) {
        // 存在验证码但是返回登录页面
        if (to.path === "/login" && isAuthenticated) {
          next({ ...from });
          NProgress.done();
          return;
        }
        //不存在角色身份就需要去获取当前登录用户的信息
        else if (Object.keys(store.getters.roles).length === 0) {
          store
            .dispatch("getUserInfo")
            .then(() => {
              loadRoute(to, next);
            })
            .catch(() => {
              location.reload();
            });
        } else if (store.getters.loadMenus) {
          store
            .dispatch("getUserInfo")
            .then(() => {
              store.dispatch("updateLoadMenus");
              loadRoute(to, next);
            })
            .catch((ee) => {
              console.log("异常2");
              console.log(ee);
              location.reload();
            });
        } else {
          // console.log('验证通过')
          next();
        }
      } else {
        const exists = router.getRoutes().find(item => item.path === to.path)
        // 不需要验证
        if (to.meta.requiresAuth || !exists) {
          next({
            path: "/login",
            // 保存我们所在的位置，以便以后再来
            query: {
              redirect: to.fullPath,
            },
          });
        } else {
          next();
        }
      }

      // 需要验证并且没有验证
      // if (to.meta.requiresAuth && !isAuthenticated) {
      //   // console.log('需要验证没有验证跳转到登陆页面')
      //   next({
      //     path: '/login',
      //     // 保存我们所在的位置，以便以后再来
      //     query: {
      //       redirect: to.fullPath
      //     }
      //   })
      // } else {
      //   // 需要验证
      //   if (isAuthenticated) {
      //     // 存在验证码但是返回登录页面
      //     if (to.path === '/login' && isAuthenticated) {
      //       next({ ...from })
      //       NProgress.done()
      //       return
      //     }
      //     else
      //       //不存在角色身份就需要去获取当前登录用户的信息
      //       if (Object.keys(store.getters.roles).length === 0) {
      //         store.dispatch('getUserInfo').then(() => {
      //           loadRoute(to, next)
      //         }).catch(() => {
      //           console.log('异常')
      //           // store.dispatch('logout').then(() => {
      //           //   // location.reload()
      //           //   store.dispatch('clearUserData')
      //           //   NProgress.done()
      //           // }).catch(() => {
      //           //   store.dispatch('clearUserData')
      //           //   NProgress.done()
      //           //   // location.reload()
      //           // })

      //         })
      //       } else if (store.getters.loadMenus) {
      //         store.dispatch('getUserInfo').then(() => {
      //           store.dispatch('updateLoadMenus')
      //           loadRoute(to, next)
      //         }).catch(() => {
      //           store.dispatch('logout').then(() => {
      //             location.reload()
      //           })
      //         })
      //       } else {
      //         // console.log('验证通过')
      //         next()
      //       }
      //   } else {
      //     // 不需要验证
      //     next()
      //   }
      // 返回false取消导航
      // return false
    }
  );

  // 全局后置钩子
  router.afterEach((to, from, failure) => {
    if (!failure) NProgress.done();
    // sendToAnalytics(to.fullPath)
  });

  const loadRoute = (to: _RouteLocationBase, next: NavigationGuardNext) => {
    buildMenus().then((res) => {
      const sdata = JSON.parse(JSON.stringify(res));
      const rdata = JSON.parse(JSON.stringify(res));

      const sidebarRoutes: Array<RouteRecordRaw> = asyncRouter(sdata);
      const rewriteRoutes: Array<RouteRecordRaw> = asyncRouter(
        rdata,
        undefined,
        true
      );

      store.dispatch("generateRoutes", rewriteRoutes).then(() => {
        // 存储路由
        // rewriteRoutes.push(router404)
        rewriteRoutes.forEach((r) => {
          router.addRoute(r); // 动态添加可访问路由表
        });
        next({
          ...to,
          replace: true,
        });
      });
      store.dispatch("setFrontMenuList", sidebarRoutes);
    });
  };
}

/**
 * Hooks for handling page state
 */
function createPageGuard(router: Router) {
  const loadedPageMap = new Map<string, boolean>();

  router.beforeEach(async (to) => {
    // The page has already been loaded, it will be faster to open it again, you don’t need to do loading and other processing
    to.meta.loaded = !!loadedPageMap.get(to.path);
    // Notify routing changes
    setRouteChange(to);

    return true;
  });

  router.afterEach((to) => {
    loadedPageMap.set(to.path, true);
  });
}

// Don't change the order of creation
export function setupRouterGuard(router: Router) {
  createPageGuard(router);
  createHttpGuard(router);
}
